///////////////////////////////////////////////////////////////////////////
//
// Spring Engine Source File.
// Copyright (C), Dengtao 2011-2021
// ----------------------------------------------------------------------
// File name:   SfMemoryTracker.cpp
// Version:     v1.0.0
// Created:     2013/06/14 21:13 by dengtao
// Compilers:   Visual Studio 2008
// Description: 
// ----------------------------------------------------------------------
// History:
//
///////////////////////////////////////////////////////////////////////////

#include "SfMemoryTracker.h"

namespace Sunflower
{

//
//Summary:
//	constructor.
MemoryTracker::MemoryTracker()
{

}

//
//Summary:
//	destructor.
MemoryTracker::~MemoryTracker()
{
	Reset();
}

//
//Summary:
//  Process Memory allocate.
void MemoryTracker::ProcMemoryAlloc(void* p, size_t size, 
	const char* fileName, int line, const char* funcName)
{
	MemoryAllocInfo* mai = CreateMai(p, size, fileName, line, funcName);

	SfAssert(m_UsingMais.find(p) == m_UsingMais.end());

	OnMemoryAlloc(mai);
		
	//
	m_UsingMais[p] = mai;
}

//
//Summary:
//	Reset
void MemoryTracker::Reset()
{
	RemoveFreeMais();
	RemoveUsingMais();
}

//
//Summary:
//	Process memory freed.
void MemoryTracker::ProcMemoryFree(void* p)
{
	MaiMapIterator it = m_UsingMais.find(p);
	SfAssert(it != m_UsingMais.end());

	OnMemoryFree(it->second);

	ReleaseMai(it->second);
	m_UsingMais.erase(it);
}

//
//Summary:
//	call-back on memory allocated.
void MemoryTracker::OnMemoryAlloc(MemoryTracker::MemoryAllocInfo* mai)
{
	SfUnreferencedParam(mai);
}

//
//Summary:
//	call-back on memory freed.
void MemoryTracker::OnMemoryFree(MemoryTracker::MemoryAllocInfo* mai)
{
	SfUnreferencedParam(mai);
}

//
//Summary:
//	create a MemoryAllocInfo object.
MemoryTracker::MemoryAllocInfo* MemoryTracker::CreateMai(void* p, size_t size, 
	const char* fileName, int line, const char* funcName)
{
	if (m_FreeMais.empty())
	{
		return new MemoryAllocInfo(p, size, fileName, line, funcName);
	}

	MemoryAllocInfo* mai = m_FreeMais.front();
	SfAssertValidPtr(mai);

	m_FreeMais.pop_front();

	MemoryAllocInfo::Make(*mai, p, size, fileName, line, funcName);

	return mai;
}

//
//Summary:
//	Destroy a mai object.
void MemoryTracker::ReleaseMai(MemoryTracker::MemoryAllocInfo* mai)
{
	SfAssertValidPtr(mai);
	m_FreeMais.push_back(mai);
}

//
//Summary:
//	Remove free Mais;
void MemoryTracker::RemoveFreeMais()
{
	for (MaiListIterator it = m_FreeMais.begin(); 
		 it != m_FreeMais.end();
		 ++it)
	{
		SfAssertValidPtr(*it);
		delete *it;
	}

	m_FreeMais.clear();
}

//
//Summary:
//	Remove using mais.
void MemoryTracker::RemoveUsingMais()
{
	for (MaiMapIterator it = m_UsingMais.begin(); 
		it != m_UsingMais.end();
		++it)
	{
		SfAssertValidPtr(it->second);
		delete it->second;
	}

	m_UsingMais.clear();
}

}